package com.xzzz.common.base.util;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;

import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 转换工具类
 *
 * @author xzzz
 * 
 */
public class ConvertUtil {

    /**
     * 整数的正则表达式
     * 支持0、1、100、-1、-100。
     * 不支持-0、-01、00、09
     */
    public static final Pattern INTEGER_PATTERN = Pattern.compile("^(0|-?[1-9][0-9]*)$");

    /**
     * 空字符串
     */
    public static final String EMPTY = "";

    /**
     * 逗号
     */
    public static final String COMMA = ",";

    /**
     * getId方法
     */
    public static final String GET_ID = "getId";

    // 下横线转驼峰标识  Lower horizontal line to hump logo

    public static final char UNDERLINE = '_';


    /**
     * 驼峰格式字符串转换为下划线格式字符串
     *
     * @param camelStr           驼峰格式的字符串
     * @param isExcludeFirstChar 是否排除第一个字符
     * @return String 下横线格式的字符串
     */
    public static String camelToUnderline(String camelStr, boolean isExcludeFirstChar) {
        if (camelStr == null || "".equals(camelStr.trim())) {
            return "";
        }
        int len = camelStr.length();
        StringBuilder sb = new StringBuilder(len);
        char c;
        for (int i = 0; i < len; i++) {
            c = camelStr.charAt(i);
            if (Character.isUpperCase(c)) {
                if (i != 0) {
                    sb.append(UNDERLINE);
                } else {
                    if (!isExcludeFirstChar) {
                        sb.append(UNDERLINE);
                    }
                }
                sb.append(Character.toLowerCase(c));
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    /**
     * 下划线格式字符串转换为驼峰格式的类名
     * 示例：_user_name  转成  UserName
     *
     * @param underlineStr 下横线格式的字符串
     * @return 驼峰格式的类名
     */
    public static String underlineToCamelClassName(String underlineStr) {
        if (underlineStr == null || "".equals(underlineStr.trim())) {
            return "";
        }
        String[] strArr = underlineStr.split("_");
        StringBuilder builder = new StringBuilder();
        for (String str : strArr) {
            builder.append(StrUtil.toCamelCase(str));
        }
        return builder.toString();
    }

    /* ----------------------------------------  将对象转成基本数据类型  -------------------------------------- */

    /**
     * 将Object转成 double
     *
     * @param obj Object对象
     * @return Double double
     */
    public static double objToDouble(Object obj) {
        if (obj instanceof Double) {
            return ((Double) obj);
        } else {
            return 0D;
        }
    }

    /* ----------------------------------------  数组与字符串之间的转换  -------------------------------------- */

    /**
     * 把数组转成字符串
     *
     * @param arr int类型的数组
     * @return String 数组字符串
     */
    public static String arrayToString(int... arr) {
        return arrayToString(COMMA, arr);
    }

    /**
     * 把数组转成字符串
     *
     * @param delimiter 字符串拼接符
     * @param arr       int类型的数组
     * @return String 数组字符串
     */
    public static String arrayToString(String delimiter, int... arr) {
        if (ArrayUtil.isEmpty(arr)) {
            return EMPTY;
        }
        return Arrays.stream(arr).boxed().map(String::valueOf).collect(Collectors.joining(delimiter));
    }

    /**
     * 将数组元素用","拼接成字符串返回
     *
     * @param arr long类型数组
     * @return String 返回的字符串
     */
    public static String arrayToString(long... arr) {
        return arrayToString(COMMA, arr);
    }

    /**
     * 把数组转成字符串
     *
     * @param delimiter 字符串连接符 delimiter
     * @param arr       long类型的数组
     * @return String 数组字符串
     */
    public static String arrayToString(String delimiter, long... arr) {
        if (ArrayUtil.isEmpty(arr)) {
            return EMPTY;
        }
        return Arrays.stream(arr).boxed().map(String::valueOf).collect(Collectors.joining(delimiter));
    }

    /**
     * 将数组元素用","拼接成字符串返回
     *
     * @param arr 引用类型数组
     * @return String 返回的字符串
     */
    @SafeVarargs
    public static <T> String arrayToString(T... arr) {
        return arrayToString(COMMA, arr);
    }

    /**
     * 将数组元素用指定字符拼接成字符串返回
     *
     * @param delimiter 连接符
     * @param arr       引用类型数组
     * @return String 返回的字符串
     */
    @SafeVarargs
    public static <T> String arrayToString(String delimiter, T... arr) {
        if (ArrayUtil.isEmpty(arr)) {
            return EMPTY;
        }
        return Arrays.stream(arr).filter(ObjectUtil::isNotEmpty).map(String::valueOf).collect(Collectors.joining(delimiter));
    }


    /**
     * 把字符串数组转成Integer[]
     *
     * @param strIds 分隔符拼接的字符串
     * @return Integer[] 数组
     */
    public static Integer[] stringToWrapperIntArray(String strIds) {
        return stringToWrapperIntArray(strIds, COMMA);
    }

    /**
     * 把字符串数组转成Integer[]
     *
     * @param strIds    分隔符拼接的字符串
     * @param delimiter 分隔符
     * @return Integer[] 数组
     */
    public static Integer[] stringToWrapperIntArray(String strIds, String delimiter) {
        if (StrUtil.isEmpty(strIds)) {
            return new Integer[0];
        }
        String[] strArr = strIds.split(delimiter);
        return Arrays.stream(strArr).filter(ObjectUtil::isNotEmpty).filter(ValidateUtil::isIntegerNumber).map(String::trim).map(Integer::valueOf).toArray(Integer[]::new);
    }

    /**
     * 把字符串数组转成int[]
     *
     * @param strIds 分隔符拼接的字符串
     * @return int[] 数组
     */
    public static int[] stringToIntArray(String strIds) {
        return stringToIntArray(strIds, COMMA);
    }

    /**
     * 把字符串数组转成int[]
     *
     * @param strIds    分隔符拼接的字符串
     * @param delimiter 分隔符
     * @return int[] 数组
     */
    public static int[] stringToIntArray(String strIds, String delimiter) {
        if (StrUtil.isEmpty(strIds)) {
            return new int[0];
        }
        String[] strArr = strIds.split(delimiter);
        return Arrays.stream(strArr).filter(ObjectUtil::isNotEmpty).filter(ValidateUtil::isIntegerNumber).map(String::trim).mapToInt(Integer::parseInt).toArray();
    }

    /**
     * 把字符串数组转成Long[]
     *
     * @param strIds 分隔符拼接的字符串
     * @return Long[] 数组
     */
    public static Long[] stringToWrapperLongArray(String strIds) {
        return stringToWrapperLongArray(strIds, COMMA);
    }

    /**
     * 把字符串数组转成Long[]
     *
     * @param strIds    分隔符拼接的字符串
     * @param delimiter 分隔符
     * @return Long[] 数组
     */
    public static Long[] stringToWrapperLongArray(String strIds, String delimiter) {
        if (StrUtil.isEmpty(strIds)) {
            return new Long[0];
        }
        String[] strArr = strIds.split(delimiter);

        return Arrays.stream(strArr).filter(ObjectUtil::isNotEmpty).filter(ValidateUtil::isIntegerNumber).map(String::trim).map(Long::valueOf).toArray(Long[]::new);
    }

    /**
     * 把字符串数组转成long[]
     *
     * @param strIds 分隔符拼接的字符串
     * @return long[] 数组
     */
    public static long[] stringToLongArray(String strIds) {
        return stringToLongArray(strIds, COMMA);
    }

    /**
     * 把字符串数组转成long[]
     *
     * @param strIds    分隔符拼接的字符串
     * @param delimiter 分隔符
     * @return long[] 数组
     */
    public static long[] stringToLongArray(String strIds, String delimiter) {
        if (StrUtil.isEmpty(strIds)) {
            return new long[0];
        }
        String[] strArr = strIds.split(delimiter);
        return Arrays.stream(strArr).filter(ObjectUtil::isNotEmpty).filter(ValidateUtil::isIntegerNumber).map(String::trim).mapToLong(Long::valueOf).toArray();
    }

    /* --------------------------------------  包装类型的数组与基本类型数组之间转换  ------------------------------------ */

    /**
     * 将原始类型数组包装为包装类型
     *
     * @param values 原始类型数组
     * @return Integer[] 包装类型数组
     */
    public static Integer[] wrap(int... values) {
        if (ArrayUtil.isEmpty(values)) {
            return new Integer[0];
        }
        return Arrays.stream(values).boxed().toArray(Integer[]::new);
    }

    /**
     * 包装类数组转为原始类型数组
     *
     * @param values 包装类型数组
     * @return int[] 原始类型数组
     */
    public static int[] unWrap(Integer... values) {
        if (ArrayUtil.isEmpty(values)) {
            return new int[0];
        }
        return Arrays.stream(values).filter(ObjectUtil::isNotNull).mapToInt(Integer::valueOf).toArray();
    }

    /**
     * 将原始类型数组包装为包装类型
     *
     * @param values 原始类型数组
     * @return Long[] 包装类型数组
     */
    public static Long[] wrap(long... values) {
        if (ArrayUtil.isEmpty(values)) {
            return new Long[0];
        }
        return Arrays.stream(values).boxed().toArray(Long[]::new);
    }

    /**
     * 包装类数组转为原始类型数组
     *
     * @param values 包装类型数组
     * @return long[] 原始类型数组
     */
    public static long[] unWrap(Long... values) {
        if (ArrayUtil.isEmpty(values)) {
            return new long[0];
        }
        return Arrays.stream(values).filter(ObjectUtil::isNotNull).mapToLong(Long::valueOf).toArray();
    }

    /**
     * 将原始类型数组包装为包装类型
     *
     * @param values 原始类型数组
     * @return Double[] 包装类型数组
     */
    public static Double[] wrap(double... values) {
        if (ArrayUtil.isEmpty(values)) {
            return new Double[0];
        }
        return Arrays.stream(values).boxed().toArray(Double[]::new);
    }

    /**
     * 包装类数组转为原始类型数组
     *
     * @param values 包装类型数组
     * @return double[] 原始类型数组
     */
    public static double[] unWrap(Double... values) {
        if (ArrayUtil.isEmpty(values)) {
            return new double[0];
        }
        return Arrays.stream(values).filter(ObjectUtil::isNotNull).mapToDouble(Double::valueOf).toArray();
    }

    /* ----------------------------------------  集合与字符串之间的转换  -------------------------------------- */

    /**
     * 根据分隔符将字符串解析成IntegerList
     *
     * @param arrStr 用分隔符拼接的字符串 eg：1,2,3
     * @return List<Integer> Integer类型的集合
     */
    public static List<Integer> stringToIntegerList(String arrStr) {
        return stringToIntegerList(arrStr, COMMA);
    }

    /**
     * 根据分隔符将字符串解析成IntegerList
     *
     * @param arrStr    用分隔符拼接的字符串 eg：1,2,3
     * @param delimiter 分隔符 eg：,或者_
     * @return List<Integer> Integer类型的集合
     */
    public static List<Integer> stringToIntegerList(String arrStr, String delimiter) {
        if (StrUtil.isEmpty(arrStr)) {
            return Collections.emptyList();
        }
        return Arrays.stream(arrStr.split(delimiter)).filter(ObjectUtil::isNotEmpty).filter(
                ValidateUtil::isIntegerNumber).map(Integer::parseInt).collect(Collectors.toList());
    }


    /**
     * 根据分隔符将字符串解析成LongList
     *
     * @param arrStr 用分隔符拼接的字符串 eg：1,2,3
     * @return List<Long> Long类型的集合
     */
    public static List<Long> stringToLongList(String arrStr) {
        return stringToLongList(arrStr, COMMA);
    }

    /**
     * 根据分隔符将字符串解析成LongList
     *
     * @param arrStr    用分隔符拼接的字符串 eg：1,2,3
     * @param delimiter 分隔符 eg：,或者_
     * @return List<Long> Long类型的集合
     */
    public static List<Long> stringToLongList(String arrStr, String delimiter) {
        if (StrUtil.isEmpty(arrStr)) {
            return new ArrayList<>();
        }
        return Arrays.stream(arrStr.split(delimiter)).filter(ObjectUtil::isNotEmpty).filter(
                ValidateUtil::isIntegerNumber).map(Long::parseLong).collect(Collectors.toList());
    }


    /**
     * 将List元素用","拼接成字符串返回
     *
     * @param collection 集合
     * @return String 返回的字符串
     */
    public static <T> String collectionToString(Collection<T> collection) {
        return collectionToString(COMMA, collection);
    }

    /**
     * 将List元素用指定字符拼接成字符串返回
     *
     * @param delimiter  连接符
     * @param collection 集合
     * @return String 返回的字符串
     */
    public static <T> String collectionToString(String delimiter, Collection<T> collection) {
        if (CollectionUtil.isEmpty(collection)) {
            return EMPTY;
        }
        return collection.stream().filter(ObjectUtil::isNotEmpty).map(String::valueOf).collect(Collectors.joining(delimiter));
    }

    public static List<String> stringToStringList(String str, String delimiter) {
        if (StrUtil.isEmpty(str)) {
            return new ArrayList<>();
        }
        return Arrays.stream(str.split(delimiter)).collect(Collectors.toList());
    }
    /* ----------------------------------------  集合与数组之间的转换  -------------------------------------- */

    /**
     * 将数组转成List
     *
     * @param arr 数组
     * @return List list集合
     */
    public static List<Integer> arrayToList(int... arr) {
        if (ArrayUtil.isEmpty(arr)) {
            return Collections.emptyList();
        }
        return Arrays.stream(arr).boxed().collect(Collectors.toList());
    }

    /**
     * 将数组转成List
     *
     * @param arr 数组
     * @return List list集合
     */
    public static List<Long> arrayToList(long... arr) {
        if (ArrayUtil.isEmpty(arr)) {
            return Collections.emptyList();
        }
        return Arrays.stream(arr).boxed().collect(Collectors.toList());
    }

    /**
     * 将数组转成List
     *
     * @param arr 数组
     * @return List list集合
     */
    @SafeVarargs
    public static <T> List<T> arrayToList(T... arr) {
        if (ArrayUtil.isEmpty(arr)) {
            return Collections.emptyList();
        }
        return Arrays.stream(arr).filter(ObjectUtil::isNotEmpty).collect(Collectors.toList());
    }

    /* ----------------------------------------  集合与集合之间的转换  -------------------------------------- */

    /**
     * 将对象的list转换成id的list
     *
     * @param list 对象List
     * @return id集合
     */
    public static <T> List<Integer> objectListToIntIdList(List<T> list) {
        return objectListToIntIdList(list, GET_ID);
    }

    /**
     * 将对象的list转换成id的list
     *
     * @param list 对象List
     * @return id集合
     */
    public static <T> List<Integer> objectListToIntIdList(List<T> list, final String method) {
        if (CollectionUtil.isEmpty(list)) {
            return Collections.emptyList();
        }
        return list.stream().filter(ObjectUtil::isNotEmpty).mapToInt(obj -> {
            try {
                return (int) obj.getClass().getMethod(method).invoke(obj);
            } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
                return 0;
            }
        }).boxed().collect(Collectors.toList());
    }

    /**
     * 将对象的list转换成id的list
     *
     * @param list 对象List
     * @return id集合
     */
    public static <T> List<Long> objectListToLongIdList(List<T> list) {
        return objectListToLongIdList(list, GET_ID);
    }

    /**
     * 将对象的list转换成id的list
     *
     * @param list 对象List
     * @return id集合
     */
    public static <T> List<Long> objectListToLongIdList(List<T> list, final String method) {
        if (CollectionUtil.isEmpty(list)) {
            return Collections.emptyList();
        }
        return list.stream().filter(ObjectUtil::isNotEmpty).mapToLong(obj -> {
            try {
                return (long) obj.getClass().getMethod(method).invoke(obj);
            } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
                return 0L;
            }
        }).boxed().collect(Collectors.toList());
    }

    /**
     * 将对象的list转换成id的list
     *
     * @param list 对象List
     * @return id集合
     */
    public static <T> List<String> objectListToStrIdList(List<T> list) {
        return objectListToStrIdList(list, GET_ID);
    }

    /**
     * 将对象的list转换成id的list
     *
     * @param list 对象List
     * @return id集合
     */
    public static <T> List<String> objectListToStrIdList(List<T> list, final String method) {
        if (CollectionUtil.isEmpty(list)) {
            return Collections.emptyList();
        }
        return list.stream().filter(ObjectUtil::isNotEmpty).map(obj -> {
            try {
                return (String) obj.getClass().getMethod(method).invoke(obj);
            } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
                return EMPTY;
            }
        }).collect(Collectors.toList());
    }


    /* ----------------------------------------  集合与map之间的转换  -------------------------------------- */


    /**
     * 将ObjectList转成以Integer为key，objectList中的元素为value的map集合
     *
     * @param list 对象List
     * @return id集合
     */
    public static <T> Map<Integer, T> objectListToIntKeyMap(List<T> list) {
        return objectListToIntKeyMap(list, GET_ID);
    }

    /**
     * 将ObjectList转成以Integer为key，objectList中的元素为value的map集合
     *
     * @param list 对象List
     * @return id集合
     */
    public static <T> Map<Integer, T> objectListToIntKeyMap(List<T> list, final String method) {
        if (CollectionUtil.isEmpty(list)) {
            return MapUtil.newHashMap();
        }
        return list.stream().filter(ObjectUtil::isNotEmpty).collect(
                Collectors.toMap(obj -> {
                    try {
                        return (Integer) obj.getClass().getMethod(method).invoke(obj);
                    } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
                        return 0;
                    }
                }, obj -> obj));
    }

    /**
     * 将ObjectList转成以Long为key，objectList中的元素为value的map集合
     *
     * @param list 对象List
     * @return id集合
     */
    public static <T> Map<Long, T> objectListToLongKeyMap(List<T> list) {
        return objectListToLongKeyMap(list, GET_ID);
    }

    /**
     * 将ObjectList转成以Long为key，objectList中的元素为value的map集合
     *
     * @param list 对象List
     * @return id集合
     */
    public static <T> Map<Long, T> objectListToLongKeyMap(List<T> list, final String method) {
        if (CollectionUtil.isEmpty(list)) {
            return MapUtil.newHashMap();
        }
        return list.stream().filter(ObjectUtil::isNotEmpty).collect(
                Collectors.toMap(obj -> {
                    try {
                        return (Long) obj.getClass().getMethod(method).invoke(obj);
                    } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
                        return 0L;
                    }
                }, obj -> obj));
    }

    /**
     * 将ObjectList转成以字符串为key，objectList中的元素为value的map集合
     *
     * @param list 对象List
     * @return id集合
     */
    public static <T> Map<String, T> objectListToStrKeyMap(List<T> list) {
        return objectListToStrKeyMap(list, GET_ID);
    }

    /**
     * 将ObjectList转成以字符串为key，objectList中的元素为value的map集合
     *
     * @param list 对象List
     * @return id集合
     */
    public static <T> Map<String, T> objectListToStrKeyMap(List<T> list, final String methodName) {
        if (CollectionUtil.isEmpty(list)) {
            return MapUtil.newHashMap();
        }
        return list.stream().filter(ObjectUtil::isNotEmpty).collect(
                Collectors.toMap(obj -> {
                    try {
                        return (String) obj.getClass().getMethod(methodName).invoke(obj);
                    } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
                        return EMPTY;
                    }
                }, obj -> obj));
    }


    /**
     * 将一个ObjectList转成key为：Long，value为objectList的Map集合
     * 应用场景：商品skuList按照商品Id进行分组
     *
     * @param objectList 对象集合
     * @param methodName 获取Long类型的key
     * @param <T>        泛型类型
     * @return Map<Long, List < T>> map集合
     */
    public static <T> Map<Long, List<T>> objectListToLongAndObjectListMap(List<T> objectList, String methodName) {
        Map<Long, List<T>> map = new HashMap<>(32);
        if (null == objectList || objectList.isEmpty()) {
            return map;
        }
        try {
            Method method = null;
            List<T> listTemp;
            Long tempKey;
            for (T t : objectList) {
                if (null == t) {
                    continue;
                }
                if (method == null) {
                    method = t.getClass().getMethod(methodName);
                }
                tempKey = (Long) method.invoke(t);
                if (map.get(tempKey) != null) {
                    map.get(tempKey).add(t);
                } else {
                    listTemp = new ArrayList<T>();
                    listTemp.add(t);
                    map.put(tempKey, listTemp);
                }
            }
        } catch (NoSuchMethodException e) {
            throw new RuntimeException("方法" + methodName + "不存在！", e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException("方法" + methodName + "访问失败！", e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException("方法" + methodName + "调用失败！", e);
        }
        return map;
    }

    /**
     * 对象转字节数组
     *
     * @param object 对象
     * @return byte[] 对象序列化后的字节数组
     */
    public static byte[] objectToByteArr(Object object) {
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
             ObjectOutputStream oos = new ObjectOutputStream(baos)) {
            oos.writeObject(object);
            return baos.toByteArray();
        } catch (IOException ex) {
            throw new RuntimeException(ex.getMessage(), ex);
        }
    }

    /**
     * 字节数组转对象
     *
     * @param bytes 直接数组
     * @return Object 字节数组反序列化的对象
     */
    public static Object byteArrToObject(byte[] bytes) {
        try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
             ObjectInputStream ois = new ObjectInputStream(bais)) {
            return ois.readObject();
        } catch (IOException | ClassNotFoundException ex) {
            throw new RuntimeException(ex.getMessage(), ex);
        }
    }

    public static void main(String[] args) {
        int[] intarr = new int[]{1, 2};
        long[] intarr1 = new long[]{1L, 4L};
        Integer[] intarr2 = new Integer[]{6, 2, 7};
        Long[] intarr3 = new Long[]{1L, 6L};
        System.out.println(arrayToList(intarr));
        System.out.println(arrayToList(intarr1));
        System.out.println(arrayToList(intarr2));
        System.out.println(arrayToList(intarr3));
        String[] intarr4 = new String[]{"asd", "123"};
        System.out.println(arrayToList(intarr4));


        System.out.println(underlineToCamelClassName(""));


        System.out.println(camelToUnderline("AabCdEf", true));
        System.out.println(camelToUnderline("aabCdEf", false));
    }

}
